/*
 * Copyright (c) 2019 The sky Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.qinker.robot.hook.plugin.dingding;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.os.Bundle;

import com.qinker.robot.common.model.Employee;
import com.qinker.robot.hook.Constant;
import com.qinker.robot.hook.data.M;
import com.qinker.robot.hook.data.ding.EmployeeObject;
import com.qinker.robot.hook.data.model.PluginInfo;
import com.qinker.robot.hook.plugin.DingCloneObject;
import com.qinker.robot.hook.plugin.base.BasePlugin;
import com.qinker.robot.hook.plugin.interfaces.XPlugin;
import com.qinker.robot.hook.plugin.interfaces.XPluginManager;
import com.qinker.robot.hook.ui.dialog.DingDingDialog;
import com.sky.xposed.common.util.Alog;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

/**
 * Created by sky on 2019/3/14.
 */
public class DingDingPlugin extends BasePlugin {


    private Handler mHandler;

    public DingDingPlugin(Build build) {
        super(build.mPluginManager);
        mHandler = build.mHandler;
    }

    @Override
    public void setEnable(int flag, boolean enable) {
//        super.setEnable(flag,  enable);    // 不需要处理
        mHandler.setEnable(flag, enable);
    }

    @Override
    public Info getInfo() {
        return new PluginInfo(Constant.Plugin.DING_DING, Constant.Name.TITLE);
    }

    @Override
    public void onHandleLoadPackage() {

        findMethod(
                getXString(M.classz.CLASS_ANDROID_SEARCH_ACTIVITY_GLOBALSEARCHACTIVITY),
                "onCreate",
                Bundle.class
        ).after(param -> {
            DingCloneObject.globalSearchFragment = XposedHelpers.getObjectField(param.thisObject, "i");
        });


        //HOOK搜索联系人信息
        /*Method a = findMethod(M.classz.CLASS_DEFPACKAGE_CONTACT_SEARCH_PRESENTER, "a", 1, "OrgNodeItemWrapperObject");
        XposedBridge.hookMethod(a, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(param.args[0]));
                Alog.d("HOOK到联系人: " + jsonObject.toJSONString());
                JSONArray orgNodeItemObjectList = jsonObject.getJSONArray("orgNodeItemObjectList");

                for (int i = 0; i < orgNodeItemObjectList.size(); i++) {
                    OrgNodeItemObject orgNodeItemObject = orgNodeItemObjectList.getJSONObject(i).toJavaObject(OrgNodeItemObject.class);
                    EmployeeObject employeeObject = orgNodeItemObject.getEmployeeObject();
                    if (userCache.containsKey(employeeObject.getOrgStaffId())) {
                        continue;
                    }
                    Employee employee = toEmployee(employeeObject);
                    userCache.put(employee.getOrgStaffId(), toEmployee(employeeObject));
                    ClientStart.send(employee);
                }
                Alog.d("本地缓存联系人: " + JSON.toJSONString(userCache));

            }
        });*/
        findMethod(
                M.classz.class_lightapp_runtime_LightAppRuntimeReverseInterfaceImpl,
                M.method.method_lightapp_runtime_LightAppRuntimeReverseInterfaceImpl_initSecurityGuard,
                Context.class)
                .before(param -> param.setResult(null));

        Method methodMessage = findMatcherMethod(
                M.classz.class_defpackage_MessageDs,
                M.method.method_defpackage_MessageDs_handler,
                String.class, Collection.class, boolean.class);

        XposedBridge.hookMethod(methodMessage, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Alog.i("收消息");

                // 处理消息
                mHandler.onHandlerMessage((String) param.args[0], (Collection) param.args[1]);
            }
        });

        findMethod(
                M.classz.class_android_dingtalk_redpackets_activities_FestivalRedPacketsPickActivity,
                M.method.method_android_dingtalk_redpackets_activities_FestivalRedPacketsPickActivity_initView)
                .after(param -> {
                    // 处理快速打开红包
                    mHandler.onHandlerFestivalRedPacketsPick((Activity) param.thisObject);
                });

        findMethod(
                M.classz.class_android_dingtalk_redpackets_activities_PickRedPacketsActivity,
                M.method.method_android_dingtalk_redpackets_activities_PickRedPacketsActivity_initView)
                .after(param -> {
                    // 处理快速打开红包
                    mHandler.onHandlerPickRedPackets((Activity) param.thisObject);
                });

        Method methodRecall = findMatcherMethod(
                M.classz.class_defpackage_MessageDs,
                M.method.method_defpackage_MessageDs_recall,
                String.class, List.class, ContentValues.class);

        XposedBridge.hookMethod(methodRecall, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);

                // 处理撤回消息
                if (mHandler.onRecallMessage((ContentValues) param.args[2])) {
                    // 直接返回0
                    param.setResult(0);
                }
            }
        });


        /****************  位置信息处理 ******************/

        findMethod(
                "com.amap.api.location.AMapLocationClient",
                "getLastKnownLocation")
                .after(param -> param.setResult(mHandler.getLastKnownLocation(param.getResult())));

        findMethod(
                "com.amap.api.location.AMapLocationClient",
                "setLocationListener",
                "com.amap.api.location.AMapLocationListener")
                .before(param -> param.args[0] = mHandler.onHandlerLocationListener(param.args[0]));
    }

    private Employee toEmployee(EmployeeObject object) {
        Employee employee = new Employee();
        employee.setOrgId(object.getOrgId());
        employee.setOrgName(object.getOrgName());
        employee.setOrgNickName(object.getOrgNickName());
        employee.setOrgStaffId(object.getOrgStaffId());
        employee.setuId(object.getUid());
        return employee;
    }


    @Override
    public void openSettings(Activity activity) {

        DingDingDialog dialog = new DingDingDialog();
        dialog.show(activity.getFragmentManager(), "dingDing");
    }

    public interface Handler {

        void setEnable(int flag, boolean enable);

        void onHandlerMessage(String cid, Collection messages);

        void onHandlerFestivalRedPacketsPick(Activity activity);

        void onHandlerPickRedPackets(Activity activity);

        boolean onRecallMessage(ContentValues contentValues);

        Object getLastKnownLocation(Object location);

        Object onHandlerLocationListener(Object listener);
    }

    public static class Build {

        private XPluginManager mPluginManager;
        private Handler mHandler;

        public Build(XPluginManager pluginManager) {
            mPluginManager = pluginManager;
        }

        public Build setHandler(Handler handler) {
            mHandler = handler;
            return this;
        }

        public XPlugin build() {
            return new DingDingPlugin(this);
        }
    }


    /**
     * 用户信息本地缓存
     */
    public static Map<String, Employee> userCache = new HashMap<>(512);
}
